/**
  @(#)$Id: AL_StackList.h 74 2013-10-10 12:42:07Z xiaoting $
  @brief     Stack (stack) in computer science is limited only in the end of the table to insert or delete operations linear form. 
  A stack is a data structure that in accordance with the principle of LIFO data storage, data is first pushed into the end of the 
  last data in the stack, you need to read the data when the data from the topmost pop. The stack is only one end of the inserted 
  and deleted special linear form. Buckets stacked items, first came under pressure in the heap, followed by a one to the heap. 
  Removed, only a one taken from above. Take the top of the heap and are carried at the bottom of the general is not moving. Stack 
  is a similar data structure barrels stacked items, delete and insert one end of said stack, said another pile bottom of the stack. 
  Insert commonly known as the push to delete is called the stack back. Also known as LIFO stack table.

  @Author $Author: xiaoting $
  @Date $Date: 2013-10-10 20:42:07 +0800 (周四, 10 十月 2013) $
  @Revision $Revision: 74 $
  @URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_StackList.h $
  @Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_StackList.h 74 2013-10-10 12:42:07Z xiaoting $
 */

#ifndef CXX_AL_STACKLIST_H
#define CXX_AL_STACKLIST_H

#ifndef CXX_AL_NODE_H
#include "AL_Node.h"
#endif

///////////////////////////////////////////////////////////////////////////
//			AL_StackList
///////////////////////////////////////////////////////////////////////////

template<typename T> 
class AL_StackList
{
public:
	/**
	* Construction
	*
	* @param
	* @return
	* @note
	* @attention
	*/
	AL_StackList();

	/**
	* Destruction
	*
	* @param
	* @return
	* @note
	* @attention
	*/
	~AL_StackList();

	/**
	* IsEmpty
	*
	* @param	VOID
	* @return	BOOL
	* @note		Returns true stack is empty
	* @attention
	*/
	BOOL IsEmpty() const;

	/**
	* Pop
	*
	* @param	T& tTypeOut <OUT>
	* @return	BOOL
	* @note		Remove the top element and return data top element
	* @attention	if empty does not return a value... (please judge the stack is empty before use it)
	*/
	BOOL Pop(T& tTypeOut);

	/**
	* Push
	*
	* @param	const T& tData
	* @return	BOOL
	* @note		Add elements in the stack
	* @attention
	*/
	BOOL Push(const T& tData);

	/**
	* Size
	*
	* @param	VOID
	* @return	DWORD
	* @note		Returns the number of elements in the stack
	* @attention
	*/
	DWORD Size() const;
	
	/**
	* Top
	*
	* @param	T& tTypeOut <OUT>
	* @return	BOOL
	* @note		Back to the top element...
	* @attention	if empty does not return a value... (please judge the stack is empty before use it)
	*/
	BOOL Top(T& tTypeOut) const;

	/**
	* Clear
	*
	* @param	VOID
	* @return	VOID
	* @note		clear all data
	* @attention
	*/
	VOID Clear();
	
protected:
private:
	/**
	*Copy Construct
	*
	* @param const AL_StackList<T>& cAL_StackList
	* @return
	*/
	AL_StackList(const AL_StackList<T>& cAL_StackList);

	/**
	*Assignment
	*
	* @param const AL_StackList<T>& cAL_StackList
	* @return AL_StackList<T>&
	*/
	AL_StackList<T>& operator = (const AL_StackList<T>& cAL_StackList);

public:
protected:
private: 
	AL_Node<T>*		m_pHeader;
	DWORD			m_dwSize;
};


/**
* Construction
*
* @param
* @return
* @note
* @attention
*/
template<typename T> 
AL_StackList<T>::AL_StackList():
m_pHeader(NULL),
m_dwSize(0x00)
{
	m_pHeader = new AL_Node<T>;
}

/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template<typename T> 
AL_StackList<T>::~AL_StackList()
{
	if (NULL != m_pHeader) {
		delete m_pHeader;
		m_pHeader = NULL;
	}
}

/**
* IsEmpty
*
* @param	VOID
* @return	BOOL
* @note		Returns true stack is empty
* @attention
*/
template<typename T> BOOL 
AL_StackList<T>::IsEmpty() const
{
	return (NULL == m_pHeader->m_pNext) ? TRUE:FALSE;
}

/**
* Pop
*
* @param	T& tTypeOut <OUT>
* @return	BOOL
* @note		Remove the top element and return data top element
* @attention	if empty does not return a value... (please judge the stack is empty before use it)
*/
template<typename T> BOOL 
AL_StackList<T>::Pop(T& tTypeOut)
{
	if (TRUE == IsEmpty()) {
		return FALSE;
	}
	
	AL_Node<T>*	pPop = m_pHeader->m_pNext;
	tTypeOut = pPop->m_tData;

	//delete the top
	m_pHeader->m_pNext = pPop->m_pNext;
	delete pPop;
	pPop = NULL;

	m_dwSize--;
	return TRUE;
}

/**
* Push
*
* @param	const T& tData
* @return	BOOL
* @note		Add elements in the stack
* @attention
*/
template<typename T> BOOL
AL_StackList<T>::Push(const T& tData)
{
	AL_Node<T>*	pPush = new AL_Node<T>;
	if (NULL == pPush) {
		//new error
		return FALSE;
	}

	pPush->m_tData = tData;
	pPush->m_pNext = m_pHeader->m_pNext;
	m_pHeader->m_pNext = pPush;

	m_dwSize++;
	return TRUE;
}

/**
* Size
*
* @param	VOID
* @return	DWORD
* @note		Returns the number of elements in the stack
* @attention
*/
template<typename T> DWORD 
AL_StackList<T>::Size() const
{
	return m_dwSize;
}

/**
* Top
*
* @param	T& tTypeOut <OUT>
* @return	BOOL
* @note		Back to the top element...
* @attention	if empty does not return a value... (please judge the stack is empty before use it)
*/
template<typename T> BOOL 
AL_StackList<T>::Top(T& tTypeOut) const
{
	if (TRUE == IsEmpty()) {
		//Empty
		return FALSE;
	}
	
	AL_Node<T>*	pTop = m_pHeader->m_pNext;
	tTypeOut = pTop->m_tData;
	return TRUE;
}

/**
* Clear
*
* @param	VOID
* @return	VOID
* @note		clear all data
* @attention
*/
template<typename T> VOID 
AL_StackList<T>::Clear()
{
	AL_Node<T>* pDelete = NULL;
	while(NULL != m_pHeader->m_pNext){
		//get the node
		pDelete = m_pHeader->m_pNext;
		m_pHeader->m_pNext = pDelete->m_pNext;
		delete pDelete;
		pDelete = NULL;
	}
	m_dwSize = 0x00;
}
#endif // CXX_AL_STACKLIST_H
/* EOF */
